/*********************************************************************************
 *      Copyright:  (C) Guo Zixuan
 *                  All rights reserved.
 *
 *       Filename:  client_socket.c
 *    Description:  This file 
 *                 
 *        Version:  1.0.0(09/04/25)
 *         Author:  Guo Zixuan <guozixuan@gmail.com>
 *      ChangeLog:  1, Release initial version on "09/04/25 20:15:41"
 *                 
 ********************************************************************************/
#include "client_socket.h"

int socket_init(socket_ctx_t *sock, char *host, int port)
{
	memset( sock, 0, sizeof(*sock) );
	sock->fd = -1;
	sock->port = port;
	sock->status = 0;
	
	if( host ) 
	{
		strncpy(sock->host, host, HOSTNAME_LEN);
	}
						 
	return 0;
}

int socket_connect(socket_ctx_t *sock)
{
	int 				rv = -1;
	struct addrinfo 	hints, *res, *p;
	char 				port_str[16];
	char 				ip_str[INET_ADDRSTRLEN];
	struct sockaddr_in *ipv4;

	sock->fd = socket(AF_INET, SOCK_STREAM, 0);
	if (sock->fd < 0) 
	{
		log_error("Create socket failure: %s\n", strerror(errno));
		return -1;
	}
	
	memset(&hints, 0, sizeof(hints));
	hints.ai_family = AF_INET;
	hints.ai_socktype = SOCK_STREAM;
	hints.ai_protocol = IPPROTO_TCP;

	snprintf(port_str, sizeof(port_str), "%d", sock->port);
	    
	rv = getaddrinfo(sock->host, port_str, &hints, &res);
	if (rv != 0)
	{
		log_error("Failed to resolve host '%s': %s\n", 
				sock->host, gai_strerror(rv));
		close(sock->fd);
		return -2;
	}

	for (p = res; p != NULL; p = p->ai_next)
	{
		ipv4 = (struct sockaddr_in *)p->ai_addr;
		inet_ntop(AF_INET, &(ipv4->sin_addr), ip_str, sizeof(ip_str));
		        
		rv = connect(sock->fd, p->ai_addr, p->ai_addrlen);
		if (rv == 0) 
		{
			sock->status = 1;
			log_info("Successfully connected to %s:%d (resolved from %s)\n",ip_str, sock->port, sock->host);
			break;
		}
		log_debug("Connect to %s:%d failed: %s\n",ip_str, sock->port, strerror(errno));
	}

	freeaddrinfo(res);

	if (rv != 0) 
	{
		log_error("Failed to connect to any address for host '%s'\n", sock->host);
		close(sock->fd);
		return -3;
	}

	return 0;
}

int socket_status(socket_ctx_t *sock) 
{
	int			error = 0;
	char		buffer[1];
	ssize_t     bytes;

	if (sock->fd < 0)
	{
		return 0; // Socket 未初始化或已关闭
	}

	socklen_t len = sizeof(error);
	if (getsockopt(sock->fd, SOL_SOCKET, SO_ERROR, &error, &len) < 0) 
	{
		return 0; // 获取错误信息失败
	}

	if (error != 0) 
	{
		 return 0; // Socket 出现错误
	}

	return 1; // Socket 连接正常
}

void socket_close(socket_ctx_t *sock)
{
	if (sock->fd > 0)
	{
		close(sock->fd);
		sock->fd = -1;
		sock->status = 0;
		log_info("Socket closed.\n");
	}
}
